#ifndef _VGUGV_COMMON_DEFINES_
#define _VGUGV_COMMON_DEFINES_

#include <array>
#include "Eigen/Dense"
#include "cudaDefs.h"
#include <pmmintrin.h>

namespace VGUGV
{
  namespace Common
  {
    #define ACCUMULATE_SUM_V4(data) (data[0] + data[1] + data[2] + data[3])
    //
    typedef unsigned char uchar;
    
    //
    enum DEVICE_TYPE
    {
      CPU,
      CUDA
    };
    
    enum ROBUST_LOSS_TYPE
    {
      PSEUDO_HUBER,
      TDISTRIBUTION
    };
    
    enum STEREO_ALG_TYPE
    {
      GROUND_TRUTH,
      SGM_FPGA, // semi-global matching
      PSW_CPU,  // plane-sweep stereo
      PSW_CUDA
    };
      
    enum TIME_TYPE
    {
      US, // microsecond
      MS, // millisecond
      S // second
    };
    
    #ifndef DCOMPILE_WITHOUT_CUDA 
    template<class T>
    struct CUDA_PitchMemory
    {
      T* dataPtr;
      size_t pitch;
      
      CUDA_PitchMemory()
      : dataPtr(NULL)
      , pitch(0){}
    };
    #endif
    
    struct GaussianDistribution
    {
      float mean;
      float variance;
      float weight;
      float nOutlier;
      float nInlier;
      
      _CPU_AND_GPU_CODE_ GaussianDistribution(float mean = 0.0f, float variance = 1e6, float weight = 0.0f)
      : mean(mean)
      , variance(variance)
      , weight(weight)
      , nOutlier(2)
      , nInlier(2){}
    };
    
    struct DepthHypothesis_GMM
    {
      EIGEN_MAKE_ALIGNED_OPERATOR_NEW
      Eigen::Vector2i pixel; // r, c
      Eigen::Vector3f unitRay;
      Eigen::Vector3f texture;
      float matchScore;
      float rayDepth;
      float variance;
      float intensity;
      short nHypothesis;
      bool bValidated;      
      bool bConverged;
      bool bDiverged;
      bool bNoGoodMatching;
      
      GaussianDistribution allHypothesis[20];
      
      _CPU_AND_GPU_CODE_ DepthHypothesis_GMM()
      : matchScore(0)
      , nHypothesis(0)
      , bValidated(false)
      , bConverged(false)
      , bDiverged(false)
      , bNoGoodMatching(false) {}
    };
    
    struct SSE_m128_m44 {
      __m128 row[4];
      
      __m128 mul(__m128 vec)
      {
	__m128 row0 = _mm_mul_ps(row[0], vec);
	__m128 row1 = _mm_mul_ps(row[1], vec);
	__m128 row2 = _mm_mul_ps(row[2], vec);
	__m128 row3 = _mm_mul_ps(row[3], vec);
	_MM_TRANSPOSE4_PS(row0, row1, row2, row3);
	return _mm_add_ps(row0, _mm_add_ps(row1, _mm_add_ps(row2, row3)));
      }
    };
    
    struct SSE_m128_v2
    {
      __m128 m[2];     
      
      SSE_m128_v2 div(float a)
      {
	__m128 sse_a = _mm_set1_ps(a);
	SSE_m128_v2 temp;
	temp.m[0] = _mm_div_ps(m[0], sse_a);
	temp.m[1] = _mm_div_ps(m[1], sse_a);
	return temp;
      }
    };
    
    struct SSE_m128_v3
    {
      __m128 m[3];      
    };
    
    struct SSE_m128_v4
    {
      __m128 m[4];
    };
    
//     float ColorMapJet[256][3] =
// 		{
// 		{0.0f, 0.0f, 0.5156f},
// 		{0.0f, 0.0f, 0.5312f},
// 		{0.0f, 0.0f, 0.5469f},
// 		{0.0f, 0.0f, 0.5625f},
// 		{0.0f, 0.0f, 0.5781f},
// 		{0.0f, 0.0f, 0.5938f},
// 		{0.0f, 0.0f, 0.6094f},
// 		{0.0f, 0.0f, 0.6250f},
// 		{0.0f, 0.0f, 0.6406f},
// 		{0.0f, 0.0f, 0.6562f},
// 		{0.0f, 0.0f, 0.6719f},
// 		{0.0f, 0.0f, 0.6875f},
// 		{0.0f, 0.0f, 0.7031f},
// 		{0.0f, 0.0f, 0.7188f},
// 		{0.0f, 0.0f, 0.7344f},
// 		{0.0f, 0.0f, 0.7500f},
// 		{0.0f, 0.0f, 0.7656f},
// 		{0.0f, 0.0f, 0.7812f},
// 		{0.0f, 0.0f, 0.7969f},
// 		{0.0f, 0.0f, 0.8125f},
// 		{0.0f, 0.0f, 0.8281f},
// 		{0.0f, 0.0f, 0.8438f},
// 		{0.0f, 0.0f, 0.8594f},
// 		{0.0f, 0.0f, 0.8750f},
// 		{0.0f, 0.0f, 0.8906f},
// 		{0.0f, 0.0f, 0.9062f},
// 		{0.0f, 0.0f, 0.9219f},
// 		{0.0f, 0.0f, 0.9375f},
// 		{0.0f, 0.0f, 0.9531f},
// 		{0.0f, 0.0f, 0.9688f},
// 		{0.0f, 0.0f, 0.9844f},
// 		{0.0f, 0.0f, 1.0000f},
// 		{0.0f, 0.0156f, 1.0000f},
// 		{0.0f, 0.0312f, 1.0000f},
// 		{0.0f, 0.0469f, 1.0000f},
// 		{0.0f, 0.0625f, 1.0000f},
// 		{0.0f, 0.0781f, 1.0000f},
// 		{0.0f, 0.0938f, 1.0000f},
// 		{0.0f, 0.1094f, 1.0000f},
// 		{0.0f, 0.1250f, 1.0000f},
// 		{0.0f, 0.1406f, 1.0000f},
// 		{0.0f, 0.1562f, 1.0000f},
// 		{0.0f, 0.1719f, 1.0000f},
// 		{0.0f, 0.1875f, 1.0000f},
// 		{0.0f, 0.2031f, 1.0000f},
// 		{0.0f, 0.2188f, 1.0000f},
// 		{0.0f, 0.2344f, 1.0000f},
// 		{0.0f, 0.2500f, 1.0000f},
// 		{0.0f, 0.2656f, 1.0000f},
// 		{0.0f, 0.2812f, 1.0000f},
// 		{0.0f, 0.2969f, 1.0000f},
// 		{0.0f, 0.3125f, 1.0000f},
// 		{0.0f, 0.3281f, 1.0000f},
// 		{0.0f, 0.3438f, 1.0000f},
// 		{0.0f, 0.3594f, 1.0000f},
// 		{0.0f, 0.3750f, 1.0000f},
// 		{0.0f, 0.3906f, 1.0000f},
// 		{0.0f, 0.4062f, 1.0000f},
// 		{0.0f, 0.4219f, 1.0000f},
// 		{0.0f, 0.4375f, 1.0000f},
// 		{0.0f, 0.4531f, 1.0000f},
// 		{0.0f, 0.4688f, 1.0000f},
// 		{0.0f, 0.4844f, 1.0000f},
// 		{0.0f, 0.5000f, 1.0000f},
// 		{0.0f, 0.5156f, 1.0000f},
// 		{0.0f, 0.5312f, 1.0f},
// 		{0.0f, 0.5469f, 1.0f},
// 		{0.0f, 0.5625f, 1.0f},
// 		{0.0f, 0.5781f, 1.0f},
// 		{0.0f, 0.5938f, 1.0f},
// 		{0.0f, 0.6094f, 1.0f},
// 		{0.0f, 0.6250f, 1.0f},
// 		{0.0f, 0.6406f, 1.0f},
// 		{0.0f, 0.6562f, 1.0f},
// 		{0.0f, 0.6719f, 1.0f},
// 		{0.0f, 0.6875f, 1.0f},
// 		{0.0f, 0.7031f, 1.0f},
// 		{0.0f, 0.7188f, 1.0f},
// 		{0.0f, 0.7344f, 1.0f},
// 		{0.0f, 0.7500f, 1.0f},
// 		{0.0f, 0.7656f, 1.0f},
// 		{0.0f, 0.7812f, 1.0f},
// 		{0.0f, 0.7969f, 1.0f},
// 		{0.0f, 0.8125f, 1.0f},
// 		{0.0f, 0.8281f, 1.0f},
// 		{0.0f, 0.8438f, 1.0f},
// 		{0.0f, 0.8594f, 1.0f},
// 		{0.0f, 0.8750f, 1.0f},
// 		{0.0f, 0.8906f, 1.0f},
// 		{0.0f, 0.9062f, 1.0f},
// 		{0.0f, 0.9219f, 1.0f},
// 		{0.0f, 0.9375f, 1.0f},
// 		{0.0f, 0.9531f, 1.0f},
// 		{0.0f, 0.9688f, 1.0f},
// 		{0.0f, 0.9844f, 1.0f},
// 		{0.0f, 1.0f, 1.0f},
// 		{0.0156f, 1.0f, 0.9844f},
// 		{0.0312f, 1.0f, 0.9688f},
// 		{0.0469f, 1.0f, 0.9531f},
// 		{0.0625f, 1.0f, 0.9375f},
// 		{0.0781f, 1.0f, 0.9219f},
// 		{0.0938f, 1.0f, 0.9062f},
// 		{0.1094f, 1.0f, 0.8906f},
// 		{0.1250f, 1.0f, 0.8750f},
// 		{0.1406f, 1.0f, 0.8594f},
// 		{0.1562f, 1.0f, 0.8438f},
// 		{0.1719f, 1.0f, 0.8281f},
// 		{0.1875f, 1.0f, 0.8125f},
// 		{0.2031f, 1.0f, 0.7969f},
// 		{0.2188f, 1.0f, 0.7812f},
// 		{0.2344f, 1.0f, 0.7656f},
// 		{0.2500f, 1.0f, 0.7500f},
// 		{0.2656f, 1.0f, 0.7344f},
// 		{0.2812f, 1.0f, 0.7188f},
// 		{0.2969f, 1.0f, 0.7031f},
// 		{0.3125f, 1.0f, 0.6875f},
// 		{0.3281f, 1.0f, 0.6719f},
// 		{0.3438f, 1.0f, 0.6562f},
// 		{0.3594f, 1.0f, 0.6406f},
// 		{0.3750f, 1.0f, 0.6250f},
// 		{0.3906f, 1.0f, 0.6094f},
// 		{0.4062f, 1.0f, 0.5938f},
// 		{0.4219f, 1.0f, 0.5781f},
// 		{0.4375f, 1.0f, 0.5625f},
// 		{0.4531f, 1.0f, 0.5469f},
// 		{0.4688f, 1.0f, 0.5312f},
// 		{0.4844f, 1.0f, 0.5156f},
// 		{0.5000f, 1.0f, 0.5000f},
// 		{0.5156f, 1.0f, 0.4844f},
// 		{0.5312f, 1.0f, 0.4688f},
// 		{0.5469f, 1.0f, 0.4531f},
// 		{0.5625f, 1.0f, 0.4375f},
// 		{0.5781f, 1.0f, 0.4219f},
// 		{0.5938f, 1.0f, 0.4062f},
// 		{0.6094f, 1.0f, 0.3906f},
// 		{0.6250f, 1.0f, 0.3750f},
// 		{0.6406f, 1.0f, 0.3594f},
// 		{0.6562f, 1.0f, 0.3438f},
// 		{0.6719f, 1.0f, 0.3281f},
// 		{0.6875f, 1.0f, 0.3125f},
// 		{0.7031f, 1.0f, 0.2969f},
// 		{0.7188f, 1.0f, 0.2812f},
// 		{0.7344f, 1.0f, 0.2656f},
// 		{0.7500f, 1.0f, 0.2500f},
// 		{0.7656f, 1.0f, 0.2344f},
// 		{0.7812f, 1.0f, 0.2188f},
// 		{0.7969f, 1.0f, 0.2031f},
// 		{0.8125f, 1.0f, 0.1875f},
// 		{0.8281f, 1.0f, 0.1719f},
// 		{0.8438f, 1.0f, 0.1562f},
// 		{0.8594f, 1.0f, 0.1406f},
// 		{0.8750f, 1.0f, 0.1250f},
// 		{0.8906f, 1.0f, 0.1094f},
// 		{0.9062f, 1.0f, 0.0938f},
// 		{0.9219f, 1.0f, 0.0781f},
// 		{0.9375f, 1.0f, 0.0625f},
// 		{0.9531f, 1.0f, 0.0469f},
// 		{0.9688f, 1.0f, 0.0312f},
// 		{0.9844f, 1.0f, 0.0156f},
// 		{1.0f, 1.0f, 0.0f},
// 		{1.0f, 0.9844f, 0.0f},
// 		{1.0f, 0.9688f, 0.0f},
// 		{1.0f, 0.9531f, 0.0f},
// 		{1.0f, 0.9375f, 0.0f},
// 		{1.0f, 0.9219f, 0.0f},
// 		{1.0f, 0.9062f, 0.0f},
// 		{1.0f, 0.8906f, 0.0f},
// 		{1.0f, 0.875f, 0.0f},
// 		{1.0f, 0.8594f, 0.0f},
// 		{1.0f, 0.8438f, 0.0f},
// 		{1.0f, 0.8281f, 0.0f},
// 		{1.0f, 0.8125f, 0.0f},
// 		{1.0f, 0.7969f, 0.0f},
// 		{1.0f, 0.7812f, 0.0f},
// 		{1.0f, 0.7656f, 0.0f},
// 		{1.0f, 0.75f, 0.0f},
// 		{1.0f, 0.7344f, 0.0f},
// 		{1.0f, 0.7188f, 0.0f},
// 		{1.0f, 0.7031f, 0.0f},
// 		{1.0f, 0.6875f, 0.0f},
// 		{1.0f, 0.6719f, 0.0f},
// 		{1.0f, 0.6562f, 0.0f},
// 		{1.0f, 0.6406f, 0.0f},
// 		{1.0f, 0.625f, 0.0f},
// 		{1.0f, 0.6094f, 0.0f},
// 		{1.0f, 0.5938f, 0.0f},
// 		{1.0f, 0.5781f, 0.0f},
// 		{1.0f, 0.5625f, 0.0f},
// 		{1.0f, 0.5469f, 0.0f},
// 		{1.0f, 0.5312f, 0.0f},
// 		{1.0f, 0.5156f, 0.0f},
// 		{1.0f, 0.5f, 0.0f},
// 		{1.0f, 0.4844f, 0.0f},
// 		{1.0f, 0.4688f, 0.0f},
// 		{1.0f, 0.4531f, 0.0f},
// 		{1.0f, 0.4375f, 0.0f},
// 		{1.0f, 0.4219f, 0.0f},
// 		{1.0f, 0.4062f, 0.0f},
// 		{1.0f, 0.3906f, 0.0f},
// 		{1.0f, 0.375f, 0.0f},
// 		{1.0f, 0.3594f, 0.0f},
// 		{1.0f, 0.3438f, 0.0f},
// 		{1.0f, 0.3281f, 0.0f},
// 		{1.0f, 0.3125f, 0.0f},
// 		{1.0f, 0.2969f, 0.0f},
// 		{1.0f, 0.2812f, 0.0f},
// 		{1.0f, 0.2656f, 0.0f},
// 		{1.0f, 0.25f, 0.0f},
// 		{1.0f, 0.2344f, 0.0f},
// 		{1.0f, 0.2188f, 0.0f},
// 		{1.0f, 0.2031f, 0.0f},
// 		{1.0f, 0.1875f, 0.0f},
// 		{1.0f, 0.1719f, 0.0f},
// 		{1.0f, 0.1562f, 0.0f},
// 		{1.0f, 0.1406f, 0.0f},
// 		{1.0f, 0.125f, 0.0f},
// 		{1.0f, 0.1094f, 0.0f},
// 		{1.0f, 0.0938f, 0.0f},
// 		{1.0f, 0.0781f, 0.0f},
// 		{1.0f, 0.0625f, 0.0f},
// 		{1.0f, 0.0469f, 0.0f},
// 		{1.0f, 0.0312f, 0.0f},
// 		{1.0f, 0.0156f, 0.0f},
// 		{1.0f, 0.0f, 0.0f},
// 		{0.9844f, 0.0f, 0.0f},
// 		{0.9688f, 0.0f, 0.0f},
// 		{0.9531f, 0.0f, 0.0f},
// 		{0.9375f, 0.0f, 0.0f},
// 		{0.9219f, 0.0f, 0.0f},
// 		{0.9062f, 0.0f, 0.0f},
// 		{0.8906f, 0.0f, 0.0f},
// 		{0.875f, 0.0f, 0.0f},
// 		{0.8594f, 0.0f, 0.0f},
// 		{0.8438f, 0.0f, 0.0f},
// 		{0.8281f, 0.0f, 0.0f},
// 		{0.8125f, 0.0f, 0.0f},
// 		{0.7969f, 0.0f, 0.0f},
// 		{0.7812f, 0.0f, 0.0f},
// 		{0.7656f, 0.0f, 0.0f},
// 		{0.75f, 0.0f, 0.0f},
// 		{0.7344f, 0.0f, 0.0f},
// 		{0.7188f, 0.0f, 0.0f},
// 		{0.7031f, 0.0f, 0.0f},
// 		{0.6875f, 0.0f, 0.0f},
// 		{0.6719f, 0.0f, 0.0f},
// 		{0.6562f, 0.0f, 0.0f},
// 		{0.6406f, 0.0f, 0.0f},
// 		{0.625f, 0.0f, 0.0f},
// 		{0.6094f, 0.0f, 0.0f},
// 		{0.5938f, 0.0f, 0.0f},
// 		{0.5781f, 0.0f, 0.0f},
// 		{0.5625f, 0.0f, 0.0f},
// 		{0.5469f, 0.0f, 0.0f},
// 		{0.5312f, 0.0f, 0.0f},
// 		{0.5156f, 0.0f, 0.0f},
// 		{0.5f, 0.0f, 0.0f}};
  }
}

#endif